// SPDX-FileCopyrightText: Copyright 2025-2025 深圳市同心圆网络有限公司
// SPDX-License-Identifier: Apache-2.0

package roadmap_data_api_serv

import (
	"context"
	"time"

	"gitcode.com/lvupclub/lvup-api/dao"
	"gitcode.com/lvupclub/lvup-api/dao/roadmap_dao"
	"gitcode.com/lvupclub/proto-gen-go.git/src/roadmap_data_api"
	"github.com/google/uuid"
	"google.golang.org/protobuf/proto"
	"google.golang.org/protobuf/types/known/anypb"
)

func (apiImpl *RoadmapDataApiImpl) AddNode(ctx context.Context, req *roadmap_data_api.AddNodeRequest) (*roadmap_data_api.AddNodeResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &roadmap_data_api.AddNodeResponse{
			Code:   roadmap_data_api.AddNodeResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//获取路线图信息
	roadmapItem, err := roadmap_dao.RoadmapInfoDao.Get(ctx, req.RoadmapId)
	if err != nil {
		return &roadmap_data_api.AddNodeResponse{
			Code:   roadmap_data_api.AddNodeResponse_CODE_NO_ROADMAP,
			ErrMsg: "成长路线图不存在",
		}, nil
	}
	//只有路线图owner可以修改
	if roadmapItem.OwnerUserId != sessItem.UserId {
		return &roadmap_data_api.AddNodeResponse{
			Code:   roadmap_data_api.AddNodeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	contentData, err := proto.Marshal(req.Content)
	if err != nil {
		return nil, err
	}

	nodeId := uuid.NewString()
	nowTime := time.Now().UnixMilli()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx context.Context) (interface{}, error) {
		err = roadmap_dao.NodeInfoDao.Insert(sessCtx, &roadmap_dao.NodeInfoDbItem{
			NodeId:      nodeId,
			RoadmapId:   req.RoadmapId,
			X:           req.X,
			Y:           req.Y,
			W:           req.W,
			H:           req.H,
			ContentData: contentData,
			CreateTime:  nowTime,
			UpdateTime:  nowTime,
		})
		if err != nil {
			return nil, err
		}
		return &roadmap_data_api.AddNodeResponse{
			Code:   roadmap_data_api.AddNodeResponse_CODE_OK,
			NodeId: nodeId,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*roadmap_data_api.AddNodeResponse), nil
}

func (apiImpl *RoadmapDataApiImpl) UpdateNodeData(ctx context.Context, req *roadmap_data_api.UpdateNodeDataRequest) (*roadmap_data_api.UpdateNodeDataResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &roadmap_data_api.UpdateNodeDataResponse{
			Code:   roadmap_data_api.UpdateNodeDataResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//获取路线图信息
	roadmapItem, err := roadmap_dao.RoadmapInfoDao.Get(ctx, req.RoadmapId)
	if err != nil {
		return &roadmap_data_api.UpdateNodeDataResponse{
			Code:   roadmap_data_api.UpdateNodeDataResponse_CODE_NO_ROADMAP,
			ErrMsg: "成长路线图不存在",
		}, nil
	}
	//只有路线图owner可以修改
	if roadmapItem.OwnerUserId != sessItem.UserId {
		return &roadmap_data_api.UpdateNodeDataResponse{
			Code:   roadmap_data_api.UpdateNodeDataResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	exist, err := roadmap_dao.NodeInfoDao.Exist(ctx, req.RoadmapId, req.NodeId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &roadmap_data_api.UpdateNodeDataResponse{
			Code:   roadmap_data_api.UpdateNodeDataResponse_CODE_NO_NODE,
			ErrMsg: "成长路线图节点不存在",
		}, nil
	}

	contentData, err := proto.Marshal(req.Content)
	if err != nil {
		return nil, err
	}

	nowTime := time.Now().UnixMilli()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx context.Context) (interface{}, error) {
		err = roadmap_dao.NodeInfoDao.UpdateData(sessCtx, req.RoadmapId, req.NodeId, contentData, nowTime)
		if err != nil {
			return nil, err
		}
		return &roadmap_data_api.UpdateNodeDataResponse{
			Code: roadmap_data_api.UpdateNodeDataResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}

	return ret.(*roadmap_data_api.UpdateNodeDataResponse), nil
}

func (apiImpl *RoadmapDataApiImpl) UpdateNodePosition(ctx context.Context, req *roadmap_data_api.UpdateNodePositionRequest) (*roadmap_data_api.UpdateNodePositionResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &roadmap_data_api.UpdateNodePositionResponse{
			Code:   roadmap_data_api.UpdateNodePositionResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//获取路线图信息
	roadmapItem, err := roadmap_dao.RoadmapInfoDao.Get(ctx, req.RoadmapId)
	if err != nil {
		return &roadmap_data_api.UpdateNodePositionResponse{
			Code:   roadmap_data_api.UpdateNodePositionResponse_CODE_NO_ROADMAP,
			ErrMsg: "成长路线图不存在",
		}, nil
	}
	//只有路线图owner可以修改
	if roadmapItem.OwnerUserId != sessItem.UserId {
		return &roadmap_data_api.UpdateNodePositionResponse{
			Code:   roadmap_data_api.UpdateNodePositionResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	exist, err := roadmap_dao.NodeInfoDao.Exist(ctx, req.RoadmapId, req.NodeId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &roadmap_data_api.UpdateNodePositionResponse{
			Code:   roadmap_data_api.UpdateNodePositionResponse_CODE_NO_NODE,
			ErrMsg: "成长路线图节点不存在",
		}, nil
	}

	nowTime := time.Now().UnixMilli()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx context.Context) (interface{}, error) {
		err = roadmap_dao.NodeInfoDao.UpdatePosition(sessCtx, req.RoadmapId, req.NodeId, req.X, req.Y, nowTime)
		if err != nil {
			return nil, err
		}
		return &roadmap_data_api.UpdateNodePositionResponse{
			Code: roadmap_data_api.UpdateNodePositionResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*roadmap_data_api.UpdateNodePositionResponse), nil
}

func (apiImpl *RoadmapDataApiImpl) UpdateNodeSize(ctx context.Context, req *roadmap_data_api.UpdateNodeSizeRequest) (*roadmap_data_api.UpdateNodeSizeResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &roadmap_data_api.UpdateNodeSizeResponse{
			Code:   roadmap_data_api.UpdateNodeSizeResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//获取路线图信息
	roadmapItem, err := roadmap_dao.RoadmapInfoDao.Get(ctx, req.RoadmapId)
	if err != nil {
		return &roadmap_data_api.UpdateNodeSizeResponse{
			Code:   roadmap_data_api.UpdateNodeSizeResponse_CODE_NO_ROADMAP,
			ErrMsg: "成长路线图不存在",
		}, nil
	}
	//只有路线图owner可以修改
	if roadmapItem.OwnerUserId != sessItem.UserId {
		return &roadmap_data_api.UpdateNodeSizeResponse{
			Code:   roadmap_data_api.UpdateNodeSizeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	exist, err := roadmap_dao.NodeInfoDao.Exist(ctx, req.RoadmapId, req.NodeId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &roadmap_data_api.UpdateNodeSizeResponse{
			Code:   roadmap_data_api.UpdateNodeSizeResponse_CODE_NO_NODE,
			ErrMsg: "成长路线图节点不存在",
		}, nil
	}

	nowTime := time.Now().UnixMilli()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx context.Context) (interface{}, error) {
		err = roadmap_dao.NodeInfoDao.UpdateSize(sessCtx, req.RoadmapId, req.NodeId, req.W, req.H, nowTime)
		if err != nil {
			return nil, err
		}
		return &roadmap_data_api.UpdateNodeSizeResponse{
			Code: roadmap_data_api.UpdateNodeSizeResponse_CODE_OK,
		}, nil
	})

	if err != nil {
		return nil, err
	}
	return ret.(*roadmap_data_api.UpdateNodeSizeResponse), nil
}

func (apiImpl *RoadmapDataApiImpl) RemoveNode(ctx context.Context, req *roadmap_data_api.RemoveNodeRequest) (*roadmap_data_api.RemoveNodeResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &roadmap_data_api.RemoveNodeResponse{
			Code:   roadmap_data_api.RemoveNodeResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//获取路线图信息
	roadmapItem, err := roadmap_dao.RoadmapInfoDao.Get(ctx, req.RoadmapId)
	if err != nil {
		return &roadmap_data_api.RemoveNodeResponse{
			Code:   roadmap_data_api.RemoveNodeResponse_CODE_NO_ROADMAP,
			ErrMsg: "成长路线图不存在",
		}, nil
	}
	//只有路线图owner可以删除
	if roadmapItem.OwnerUserId != sessItem.UserId {
		return &roadmap_data_api.RemoveNodeResponse{
			Code:   roadmap_data_api.RemoveNodeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	exist, err := roadmap_dao.NodeInfoDao.Exist(ctx, req.RoadmapId, req.NodeId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &roadmap_data_api.RemoveNodeResponse{
			Code: roadmap_data_api.RemoveNodeResponse_CODE_OK,
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx context.Context) (interface{}, error) {
		//删除节点
		err = roadmap_dao.NodeInfoDao.Remove(sessCtx, req.RoadmapId, req.NodeId)
		if err != nil {
			return nil, err
		}
		//删除相关边
		err = roadmap_dao.EdgeInfoDao.RemoveByFromNode(sessCtx, req.RoadmapId, req.NodeId)
		if err != nil {
			return nil, err
		}
		err = roadmap_dao.EdgeInfoDao.RemoveByToNode(sessCtx, req.RoadmapId, req.NodeId)
		if err != nil {
			return nil, err
		}
		//删除节点相关学习状态
		return &roadmap_data_api.RemoveNodeResponse{
			Code: roadmap_data_api.RemoveNodeResponse_CODE_OK,
		}, nil
	})

	if err != nil {
		return nil, err
	}
	return ret.(*roadmap_data_api.RemoveNodeResponse), nil
}

func (apiImpl *RoadmapDataApiImpl) ListNode(ctx context.Context, req *roadmap_data_api.ListNodeRequest) (*roadmap_data_api.ListNodeResponse, error) {
	emptyList := []*roadmap_data_api.NodeInfo{}

	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &roadmap_data_api.ListNodeResponse{
			Code:     roadmap_data_api.ListNodeResponse_CODE_WRONG_SESSION,
			ErrMsg:   "会话不存在",
			NodeList: emptyList,
		}, nil
	}
	//获取路线图信息
	roadmapItem, err := roadmap_dao.RoadmapInfoDao.Get(ctx, req.RoadmapId)
	if err != nil {
		return &roadmap_data_api.ListNodeResponse{
			Code:     roadmap_data_api.ListNodeResponse_CODE_NO_ROADMAP,
			ErrMsg:   "成长路线图不存在",
			NodeList: emptyList,
		}, nil
	}
	//只有路线图owner和路线图成员可以访问
	if roadmapItem.OwnerUserId != sessItem.UserId {
		exist, err := roadmap_dao.RoadmapMemberDao.Exist(ctx, req.RoadmapId, sessItem.UserId)
		if err != nil {
			return nil, err
		}
		if !exist {
			return &roadmap_data_api.ListNodeResponse{
				Code:     roadmap_data_api.ListNodeResponse_CODE_NO_PERMISSION,
				ErrMsg:   "没有权限",
				NodeList: emptyList,
			}, nil
		}
	}

	nodeItemList, err := roadmap_dao.NodeInfoDao.List(ctx, req.RoadmapId)
	if err != nil {
		return nil, err
	}

	nodeList := []*roadmap_data_api.NodeInfo{}
	for _, nodeItem := range nodeItemList {
		node, err := nodeItem.ToNodeInfo()
		if err != nil {
			continue
		}
		nodeList = append(nodeList, node)
	}
	return &roadmap_data_api.ListNodeResponse{
		Code:     roadmap_data_api.ListNodeResponse_CODE_OK,
		NodeList: nodeList,
	}, nil
}

func (apiImpl *RoadmapDataApiImpl) GetNode(ctx context.Context, req *roadmap_data_api.GetNodeRequest) (*roadmap_data_api.GetNodeResponse, error) {
	emptyInfo := &roadmap_data_api.NodeInfo{
		Content: &anypb.Any{},
	}

	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &roadmap_data_api.GetNodeResponse{
			Code:   roadmap_data_api.GetNodeResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
			Node:   emptyInfo,
		}, nil
	}
	//获取路线图信息
	roadmapItem, err := roadmap_dao.RoadmapInfoDao.Get(ctx, req.RoadmapId)
	if err != nil {
		return &roadmap_data_api.GetNodeResponse{
			Code:   roadmap_data_api.GetNodeResponse_CODE_NO_ROADMAP,
			ErrMsg: "成长路线图不存在",
			Node:   emptyInfo,
		}, nil
	}
	//只有路线图owner和路线图成员可以访问
	if roadmapItem.OwnerUserId != sessItem.UserId {
		exist, err := roadmap_dao.RoadmapMemberDao.Exist(ctx, req.RoadmapId, sessItem.UserId)
		if err != nil {
			return nil, err
		}
		if !exist {
			return &roadmap_data_api.GetNodeResponse{
				Code:   roadmap_data_api.GetNodeResponse_CODE_NO_PERMISSION,
				ErrMsg: "没有权限",
				Node:   emptyInfo,
			}, nil
		}
	}

	nodeItem, err := roadmap_dao.NodeInfoDao.Get(ctx, req.RoadmapId, req.NodeId)
	if err != nil {
		return &roadmap_data_api.GetNodeResponse{
			Code:   roadmap_data_api.GetNodeResponse_CODE_NO_NODE,
			ErrMsg: "成长路线图节点不存在",
			Node:   emptyInfo,
		}, nil
	}
	node, err := nodeItem.ToNodeInfo()
	if err != nil {
		return nil, err
	}

	return &roadmap_data_api.GetNodeResponse{
		Code: roadmap_data_api.GetNodeResponse_CODE_OK,
		Node: node,
	}, nil
}
